package com.ktg.mes.util;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ktg.common.utils.DateUtils;
import com.ktg.mes.unit.tableVersion.domain.ZjmTable;

import javax.security.sasl.SaslServer;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.text.DateFormat;
import java.util.*;

public class LGQueryWrapper<T> extends QueryWrapper<T>{

    private Map<String,Object> thisMap;

    // map key支持 between 之间
    private final static String keyStartFx = "_start";
    private final static String keyEndFx = "_end";

    Map<String,Field> tableColumnFieldMap = new HashMap<>() ;


    /**
     *  map key支持 like 右边模糊查询, 查询格式：'ss%' , 模糊查询字段之间用英文逗号分割：,
     *  如：{
     *      "lgQueryLikeRight":"device_name,record_id"
     *  }
      */
    private final static String keyLikeRightString = "lg_query_like_right"; //同时支持大小写：lg_query_like_right 和 lgQueryLikeRight


    /**
     *  map key支持 日期 查询精确到：年,月,日,小时,分钟，模糊查询字段之间用英文逗号分割：,
     *  如：{
     *      "lgDateHourString":"create_time,update_time"
     *  }
     */
    private final static String keyDateMinuteString = "lg_date_minute_string"; //同时支持大小写：lg_date_minute_string 和 lgDateMinuteString
    private final static String keyDateHourString = "lg_date_hour_string"; //同时支持大小写：lg_date_hour_string 和 lgDateHourString

    private final static String keyDateDayString = "lg_date_day_string"; //同时支持大小写：lg_date_day_string 和 lgDateDayString
    private final static String keyDateMonthString = "lg_date_month_string"; //同时支持大小写：lg_date_month_string 和 lgDateMonthString
    private final static String keyDateYearString = "lg_date_year_string"; //同时支持大小写：lg_date_year_string 和 lgDateYearString


    private String[] thisLikeRightStringList;

    private String[] thisDateMinuteStringList;
    private String[] thisDateHourStringList;

    private String[] thisDateDayStringList;
    private String[] thisDateMonthStringList;
    private String[] thisDateYearStringList;
    public LGQueryWrapper(Object object, Map map){
        thisMap = new HashMap<>();
        if (map != null){
            Set<String> keySet = map.keySet();
            for (String key:keySet) {
                thisMap.put(camelToUnderline(key),map.get(key));
            }
        }

        // like String
        if (thisMap.get(keyLikeRightString) != null){
            String str = null;
            if (thisMap.get(keyLikeRightString) instanceof String){
                str = (String) thisMap.get(keyLikeRightString);
            }else {
                str = ((String[]) thisMap.get(keyLikeRightString))[0];
            }
            thisLikeRightStringList = str.split(",");
        }

        // 按分钟查询
        if (thisMap.get(keyDateMinuteString) != null){
            String str = null;
            if (thisMap.get(keyDateMinuteString) instanceof String){
                str = (String) thisMap.get(keyDateMinuteString);
            }else {
                str = ((String[]) thisMap.get(keyDateMinuteString))[0];
            }
            thisDateMinuteStringList = str.split(",");
        }

        // 按小时查询
        if (thisMap.get(keyDateHourString) != null){
            String str = null;
            if (thisMap.get(keyDateHourString) instanceof String){
                str = (String) thisMap.get(keyDateHourString);
            }else {
                str = ((String[]) thisMap.get(keyDateHourString))[0];
            }
            thisDateHourStringList = str.split(",");
        }

        // 按天查询
        if (thisMap.get(keyDateDayString) != null){
            String str = null;
            if (thisMap.get(keyDateDayString) instanceof String){
                str = (String) thisMap.get(keyDateDayString);
            }else {
                str = ((String[]) thisMap.get(keyDateDayString))[0];
            }
            thisDateDayStringList = str.split(",");
        }

        // 按月查询
        if (thisMap.get(keyDateMonthString) != null){
            String str = null;
            if (thisMap.get(keyDateMonthString) instanceof String){
                str = (String) thisMap.get(keyDateMonthString);
            }else {
                str = ((String[]) thisMap.get(keyDateMonthString))[0];
            }
            thisDateMonthStringList = str.split(",");
        }

        // 按年查询
        if (thisMap.get(keyDateYearString) != null){
            String str = null;
            if (thisMap.get(keyDateYearString) instanceof String){
                str = (String) thisMap.get(keyDateYearString);
            }else {
                str = ((String[]) thisMap.get(keyDateYearString))[0];
            }
            thisDateYearStringList = str.split(",");
        }

        if (object != null){
            dealObject(object);
        }
    }


    private void dealObject(Object object){
        Class<?> aClass = object.getClass();
        List<Field> fieldList = new ArrayList<>() ;
        tableColumnFieldMap = new HashMap<>();
        Class<?> tClass = aClass;
        while (tClass != null) {//当父类为null的时候说明到达了最上层的父类(Object类).
            fieldList.addAll(Arrays.asList(tClass.getDeclaredFields()));
            tClass = tClass.getSuperclass(); //得到父类,然后赋给自己
        }
        try {
            String lasFindKey = null;
            for (int i = 0;i < fieldList.size();i++){
                Field field = fieldList.get(i);
                if (Modifier.isFinal(field.getModifiers())){
                    continue;
                }
                field.setAccessible(true);
                TableField tableField = field.getAnnotation(TableField.class);
                if (tableField != null && tableField.exist() == false) {
                    continue;
                }
                String tableFieldName = "";
                if (tableField != null && tableField.value() != null){
                    tableFieldName = tableField.value();
                }else {
                    tableFieldName = camelToUnderline(field.getName());
                }
                if (tableFieldName.equals(lasFindKey)){
                    continue;
                }
                lasFindKey = tableFieldName;
                tableColumnFieldMap.put(tableFieldName,field);

                //开始结束
                String startStr = tableFieldName+keyStartFx;
                String endStr = tableFieldName+keyEndFx;
                Object startVal = thisMap.get(startStr);
                Object endVal = thisMap.get(endStr);
                if (startVal != null || endVal != null){
                    String s = field.getType().getName();
                    if (s.endsWith(".Date")){
                        if (startVal != null){
                            if (startVal instanceof String){
                                startVal = toDataValueComplement((String) startVal);
                            }else {
                                String[] aa = (String[])startVal;
                                startVal = toDataValueComplement(aa[0]);
                            }
                        }
                        if (endVal != null){
                            if (endVal instanceof String){
                                endVal = toDataValueComplement((String) endVal);
                            }else {
                                String[] aa = (String[])endVal;
                                endVal = toDataValueComplement(aa[0]);
                            }
                        }
                    }
                    if (startVal == null){
                        le(tableFieldName,DateUtil.parse(endVal.toString(), DateUtils.YYYY_MM_DD_HH_MM_SS));
                    }else if (endVal == null){
                        ge(tableFieldName,DateUtil.parse(startVal.toString(), DateUtils.YYYY_MM_DD_HH_MM_SS));
                    }else {
                        between(tableFieldName,
                                DateUtil.parse(startVal.toString(), DateUtils.YYYY_MM_DD_HH_MM_SS),
                                DateUtil.parse(endVal.toString(), DateUtils.YYYY_MM_DD_HH_MM_SS));
                    }
                }else {
                    Object valueObject = field.get(object);
                    if (valueObject == null || (valueObject instanceof String &&  valueObject.toString().length() == 0)){
                        continue;
                    }
                    String s = field.getType().getName();
                    if (s.endsWith(".Date")){
                        queryDateType(tableFieldName,valueObject);
                    }else if (valueObject instanceof String){
                        String thisStr = (String) valueObject;
                        boolean isLike = false;
                        if (thisLikeRightStringList != null && thisLikeRightStringList.length > 0){
                            for (int j = 0; j < thisLikeRightStringList.length; j++) {
                                if (thisLikeRightStringList[j].equals(tableFieldName)){
                                    isLike = true;
                                    break;
                                };
                            }
                        }
                        if (isLike){
                            // 判断是否模糊查询
                            likeRight(tableFieldName,thisStr);
                        }else {
                            eq(tableFieldName,thisStr);
                        };
                    }else {
                        eq(tableFieldName,valueObject);
                    }
                }


            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }




    /**
     * 查询日期精确度处理
     * @param tableFieldName
     * @param valueObject
     */
    private void  queryDateType(String tableFieldName,Object valueObject){

        if (valueObject instanceof Date){
            valueObject = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS,(Date) valueObject);
        }else if (valueObject instanceof String){
            valueObject = toDataValueComplement((String) valueObject);
        }else {
            String[] aa = (String[])valueObject;
            valueObject = toDataValueComplement(aa[0]);
        }
        String dataStr = (String) valueObject;

        int dateType = 0;

        // 按天查询
        if (dateType == 0){
            if (thisDateDayStringList != null && thisDateDayStringList.length > 0){
                for (int j = 0; j < thisDateDayStringList.length; j++) {
                    if (thisDateDayStringList[j].equals(tableFieldName)){
                        dateType = 3;
                        break;
                    };
                }
            }
        }

        //按年月查询
        if (dateType == 0){
            if (thisDateMonthStringList != null && thisDateMonthStringList.length > 0){
                for (int j = 0; j < thisDateMonthStringList.length; j++) {
                    if (thisDateMonthStringList[j].equals(tableFieldName)){
                        dateType = 2;
                        break;
                    };
                }
            }
        }

        //按年查询
        if (dateType == 0) {
            if (thisDateYearStringList != null && thisDateYearStringList.length > 0) {
                for (int j = 0; j < thisDateYearStringList.length; j++) {
                    if (thisDateYearStringList[j].equals(tableFieldName)) {
                        dateType = 1;
                        break;
                    };
                }
            }
        }

        //按小时查询
        if (dateType == 0) {
            if (thisDateHourStringList != null && thisDateHourStringList.length > 0) {
                for (int j = 0; j < thisDateHourStringList.length; j++) {
                    if (thisDateHourStringList[j].equals(tableFieldName)) {
                        dateType = 4;
                        break;
                    };
                }
            }
        }

        //按分钟查询
        if (dateType == 0) {
            if (thisDateMinuteStringList != null && thisDateMinuteStringList.length > 0) {
                for (int j = 0; j < thisDateMinuteStringList.length; j++) {
                    if (thisDateMinuteStringList[j].equals(tableFieldName)) {
                        dateType = 5;
                        break;
                    };
                }
            }
        }

        //根据时间长度查询相对应的日期
        if (dateType == 0){
            eq(tableFieldName,dataStr);
        }else if(dateType == 5){
            eq("DATE_FORMAT("+tableFieldName+",'%Y-%m-%d %H:%i')",dataStr.substring(0,16));
        }else if(dateType == 4){
            eq("DATE_FORMAT("+tableFieldName+",'%Y-%m-%d %H')",dataStr.substring(0,13));
        }else if(dateType == 3){
            eq("DATE_FORMAT("+tableFieldName+",'%Y-%m-%d')",dataStr.substring(0,10));
        }else if(dateType == 2){
            eq("DATE_FORMAT("+tableFieldName+",'%Y-%m')",dataStr.substring(0,7));
        }else if(dateType == 1){
            eq("DATE_FORMAT("+tableFieldName+",'%Y')",dataStr.substring(0,4));
        }
    }



    /**
     * 将驼峰命名转化成下划线
     * @param para
     * @return
     */
    public String camelToUnderline(String para){
        if(para.length()<3){
            return para.toLowerCase();
        }
        StringBuilder sb=new StringBuilder(para);
        int temp=0;//定位
        //从第三个字符开始 避免命名不规范
        for(int i=2;i<para.length();i++){
            if(Character.isUpperCase(para.charAt(i))){
                sb.insert(i+temp, "_");
                temp+=1;
            }
        }
        return sb.toString().toLowerCase();
    }


    /**
     * 补齐日期正确写法
     * @param para
     * @return
     */
    public String toDataValueComplement(String para){
        String dayStr = DateUtils.dataStringValueComplement(para);
        return dayStr;
    }



}
